package cn.edu.sgu.www.mhxysy.service.equipment.impl;

import cn.edu.sgu.www.mhxysy.pager.Pager;
import cn.edu.sgu.www.mhxysy.dto.equipment.EquipmentAttributeDTO;
import cn.edu.sgu.www.mhxysy.entity.equipment.Equipment;
import cn.edu.sgu.www.mhxysy.entity.equipment.EquipmentAttribute;
import cn.edu.sgu.www.mhxysy.entity.equipment.EquipmentCategory;
import cn.edu.sgu.www.mhxysy.entity.equipment.EquipmentViewAttribute;
import cn.edu.sgu.www.mhxysy.enums.EquipmentAttributeTypes;
import cn.edu.sgu.www.mhxysy.enums.OperationTypes;
import cn.edu.sgu.www.mhxysy.exception.GlobalException;
import cn.edu.sgu.www.mhxysy.mapper.equipment.*;
import cn.edu.sgu.www.mhxysy.pager.equipment.EquipmentAttributePager;
import cn.edu.sgu.www.mhxysy.restful.ResponseCode;
import cn.edu.sgu.www.mhxysy.service.equipment.EquipmentAttributeService;
import cn.edu.sgu.www.mhxysy.vo.except.AttributeVO;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;

/**
 * @author 沐雨橙风ιε
 * @version 1.0
 */
@Service
public class EquipmentAttributeServiceImpl implements EquipmentAttributeService {

	private final ThreadLocal<Integer> threadLocal = new ThreadLocal<>();

	private final EquipmentMapper equipmentMapper;
	private final EquipmentTypeMapper equipmentTypeMapper;
	private final EquipmentCategoryMapper equipmentCategoryMapper;
	private final EquipmentAttributeMapper equipmentAttributeMapper;
	private final EquipmentViewAttributeMapper equipmentViewAttributeMapper;

	@Autowired
	public EquipmentAttributeServiceImpl(
			EquipmentMapper equipmentMapper,
			EquipmentTypeMapper equipmentTypeMapper,
			EquipmentCategoryMapper equipmentCategoryMapper,
			EquipmentAttributeMapper equipmentAttributeMapper,
			EquipmentViewAttributeMapper equipmentViewAttributeMapper) {
		this.equipmentMapper = equipmentMapper;
		this.equipmentTypeMapper = equipmentTypeMapper;
		this.equipmentCategoryMapper = equipmentCategoryMapper;
		this.equipmentAttributeMapper = equipmentAttributeMapper;
		this.equipmentViewAttributeMapper = equipmentViewAttributeMapper;
	}

	@Override
	public void insert(EquipmentAttributeDTO equipmentAttributeDTO) {
		threadLocal.set(OperationTypes.TJ.getValue());

		boolean result = validateRange(equipmentAttributeDTO);

		if (result) {
			EquipmentAttribute equipmentAttribute = toEntity(equipmentAttributeDTO);

			equipmentAttribute.setId(equipmentAttribute.uuid());

			equipmentAttributeMapper.insert(equipmentAttribute);
		}
	}

	@Override
	public void deleteById(String id) {
		int rows = equipmentAttributeMapper.deleteById(id);

		if (rows != 1) {
			throw new GlobalException(ResponseCode.BAD_REQUEST, "操作异常，本次操作删除了" + rows + "条记录~");
		}
	}

	@Override
	public void updateById(EquipmentAttributeDTO equipmentAttributeDTO) {
		threadLocal.set(OperationTypes.XG.getValue());

		boolean result = validateRange(equipmentAttributeDTO);

		if (result) {
			EquipmentAttribute equipmentAttribute = toEntity(equipmentAttributeDTO);

			int rows = equipmentAttributeMapper.updateById(equipmentAttribute);

			if (rows != 1) {
				throw new GlobalException(ResponseCode.BAD_REQUEST, "操作异常，本次操作修改了" + rows + "条记录~");
			}
		}
	}

	@Override
	public List<AttributeVO> selectAttributes(String equipmentId) {
		return equipmentAttributeMapper.selectAttributes(equipmentId);
	}

	@Override
	public Page<EquipmentAttribute> selectByPage(EquipmentAttributePager pager) {
		Page<EquipmentAttribute> page = Pager.ofPage(pager);

		return equipmentAttributeMapper.selectByPage(page, pager.getEquipmentId());
	}

	/**
	 * 验证属性范围
	 * @param equipmentAttributeDTO 装备属性信息
	 */
	private boolean validateRange(EquipmentAttributeDTO equipmentAttributeDTO) {
		// 得到属性类型
		Integer type = equipmentAttributeDTO.getType();
		Integer propertyId = equipmentAttributeDTO.getPropertyId();

		// 验证普通属性的范围，熔炼属性不验证
		if (EquipmentAttributeTypes.PUTONG.getValue().equals(type)) {
			Equipment equipment = equipmentMapper.selectById(equipmentAttributeDTO.getEquipmentId());
			EquipmentCategory equipmentCategory = equipmentCategoryMapper.selectById(equipment.getCategoryId());
			Integer equipmentId = equipmentTypeMapper.selectTopType(equipmentCategory.getId());

			/*
			 * 查询装备预览属性
			 */
			QueryWrapper<EquipmentViewAttribute> queryWrapper = new QueryWrapper<>();

			queryWrapper.eq("property_id", propertyId);
			queryWrapper.eq("equipment_id", equipmentId);
			queryWrapper.eq("forge_type", equipment.getForgeType());
			queryWrapper.eq("grade", equipmentCategory.getGrade());

			EquipmentViewAttribute viewAttribute = equipmentViewAttributeMapper.selectOne(queryWrapper);

			// 验证属性范围
			if (viewAttribute != null) {
				Integer max = viewAttribute.getMax();
				Integer min = viewAttribute.getMin();

				if (equipmentAttributeDTO.getPropertyValue() > max || equipmentAttributeDTO.getPropertyValue() < min) {
					String errorMessage = "属性值不合法，数值范围为：" + min + "~" + max;

					throw new GlobalException(ResponseCode.BAD_REQUEST, errorMessage);
				}
			}
		}

		Integer operationType = threadLocal.get();
		String attributeId = equipmentAttributeDTO.getId();
		String equipmentId = equipmentAttributeDTO.getEquipmentId();

		/*
		 * 验证装备的重复属性
		 */
		QueryWrapper<EquipmentAttribute> queryWrapper = new QueryWrapper<>();

		queryWrapper.eq("equipment_id", equipmentId);
		queryWrapper.eq("property_id", propertyId);
		queryWrapper.eq("type", type);
		queryWrapper.ne(
				OperationTypes.XG.getValue().equals(operationType),
				"id", attributeId
		);

		Long count = equipmentAttributeMapper.selectCount(queryWrapper);

		if (count > 0) {
			String errorMessage = "操作失败，属性重复。";

			throw new GlobalException(ResponseCode.BAD_REQUEST, errorMessage);
		}

		/*
		 * 熔炼属性：验证是否有同类型的普通属性
		 */
		if (EquipmentAttributeTypes.RONGLIAN.getValue().equals(type)) {
			queryWrapper.clear();

			queryWrapper.eq("property_id", propertyId);
			queryWrapper.eq("equipment_id", equipmentId);
			queryWrapper.eq("type", EquipmentAttributeTypes.PUTONG.getValue());
			queryWrapper.ne(
					OperationTypes.XG.getValue().equals(operationType),
					"id", attributeId
			);

			count = equipmentAttributeMapper.selectCount(queryWrapper);

			if (count == 0) {
				String errorMessage = "属性不合法，未找到与之相同的普通属性。";

				throw new GlobalException(ResponseCode.BAD_REQUEST, errorMessage);
			}
		}

		return true;
	}

	private EquipmentAttribute toEntity(EquipmentAttributeDTO equipmentAttributeDTO) {
		EquipmentAttribute equipmentAttribute = new EquipmentAttribute();

		equipmentAttribute.setId(equipmentAttributeDTO.getId());
		equipmentAttribute.setType(equipmentAttributeDTO.getType());
		equipmentAttribute.setPropertyId(equipmentAttributeDTO.getPropertyId());
		equipmentAttribute.setEquipmentId(equipmentAttributeDTO.getEquipmentId());
		equipmentAttribute.setPropertyValue(equipmentAttributeDTO.getPropertyValue());

		return equipmentAttribute;
	}

}